package com.swak.persistence.mybatis.injector;

import static java.util.stream.Collectors.toList;

import java.util.List;
import java.util.stream.Stream;

import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.swak.define.TableDefine;
import com.swak.define.TableDefines;
import com.swak.persistence.BaseMapper;
import com.swak.persistence.mybatis.methods.CURDMethod;
import com.swak.persistence.mybatis.methods.impls.BatchInsert;
import com.swak.persistence.mybatis.methods.impls.CountByCondition;
import com.swak.persistence.mybatis.methods.impls.CountBySelective;
import com.swak.persistence.mybatis.methods.impls.Delete;
import com.swak.persistence.mybatis.methods.impls.DeleteSelective;
import com.swak.persistence.mybatis.methods.impls.Exists;
import com.swak.persistence.mybatis.methods.impls.ExistsByCondition;
import com.swak.persistence.mybatis.methods.impls.ExistsSelective;
import com.swak.persistence.mybatis.methods.impls.Get;
import com.swak.persistence.mybatis.methods.impls.GetSelective;
import com.swak.persistence.mybatis.methods.impls.GetUnique;
import com.swak.persistence.mybatis.methods.impls.Insert;
import com.swak.persistence.mybatis.methods.impls.Insertive;
import com.swak.persistence.mybatis.methods.impls.Lock;
import com.swak.persistence.mybatis.methods.impls.Merge;
import com.swak.persistence.mybatis.methods.impls.QueryByCondition;
import com.swak.persistence.mybatis.methods.impls.QueryByConditionSelective;
import com.swak.persistence.mybatis.methods.impls.QuerySelective;
import com.swak.persistence.mybatis.methods.impls.ResultMap;
import com.swak.persistence.mybatis.methods.impls.Update;
import com.swak.persistence.mybatis.methods.impls.UpdateSelective;
import com.swak.persistence.mybatis.methods.impls.Updative;

/**
 * Sql 注入
 * 
 * @author lifeng
 * @date 2021年1月21日 下午4:19:42
 */
public class SqlInjector {

	protected static final Logger logger = LoggerFactory.getLogger(CURDMethod.class);

	/**
	 * 检查SQL是否注入(已经注入过不再注入)
	 *
	 * @param builderAssistant mapper 信息
	 * @param mapperClass      mapper 接口的 class 对象
	 */
	public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
		try {
			if (!this.matchAutoCurd(mapperClass)) {
				return;
			}
			TableDefine<?> table = TableDefines.newDefineUseMapper(mapperClass);
			List<CURDMethod> methodList = this.getMethods(mapperClass);
			methodList.forEach(m -> m.inject(builderAssistant, table));
		} catch (Exception e) {
			logger.error("Inject Sql Error", e);
		}
	}

	/**
	 * 特殊的类才需要自动注入 CURD
	 */
	private boolean matchAutoCurd(Class<?> mapperClass) {
		if (BaseMapper.class.isAssignableFrom(mapperClass)) {
			return true;
		}
		return false;
	}

	/**
	 * 获取 注入的方法
	 */
	protected List<CURDMethod> getMethods(Class<?> mapperClass) {
		return Stream.of(new ResultMap(), new Get(), new Insert(), new Insertive(), new BatchInsert(), new Update(),
				new Delete(), new QueryByCondition(), new CountByCondition(), new Exists(), new Lock(),
				new UpdateSelective(), new DeleteSelective(), new GetSelective(), new QueryByConditionSelective(),
				new GetUnique(), new Updative(), new QuerySelective(), new CountBySelective(),
				// ----- 删除 -----
				// new ClearSelective(),
				// new Version(),
				// new Replace(), new Toggle(), new Statistics(),
				// ---------------
				new Merge(), new ExistsByCondition(), new ExistsSelective()).collect(toList());
	}
}
